package juc.popular;

import java.util.concurrent.TimeUnit;

/**
 * 1. 可见性
 * * jvm内存模型,分为工作区和主内存区
 * * 线程对变量进行操作时,先将变量拷贝到自己工作内存,修改后再同步回主内存
 * * 在线程修改完,还没有同步回主内存时,其它线程是看不到变量的修改的
 * * 而volatile修饰的变量,每次在工作内存修改后会强制同步回主内存
 * * 并使其它线程的缓存失效(失效后下次读取就要回主内存读取),保持变量的可见性
 * <p>
 * 2. 有序性
 * * volatile会禁止[指令重排序优化],保证治疗的顺序性
 * * [指令重排序优化]可能会调整代码的执行顺序,在多线程下可能会出现问题
 * <p>
 * 3. 不保证原子性
 * * 对于非原子的操作,如i++,volatile并不能保证i++的结果立马对其它线程可见
 * * 因为i++是分解为三步进行: 获取i的值,计算出i+1,将结果写回i
 * * 而如i = 10,这样的赋值操作就是原子操作,volatile可保证这个操作的可见性
 * <p>
 * 1. 对变量的写入操作不依赖变量的当前值,或者你能确保只有单个线程更新变量的值
 * 2. 该变量没有包含在具有其他变量的不变式中
 *
 * @author 王霄
 * @date 2021/9/19 21:49
 */
public class VolatileDemo {

    private static volatile boolean SIGN = false;

    public static void main(String[] args) {
        new TaskOne().start();
        new TaskTwo().start();
    }

    public static class TaskOne extends Thread {
        @Override
        public void run() {
            while (!SIGN) {
                System.out.println("sign是False，继续");
            }
            System.out.println("sign被修改为True，退出");
        }
    }

    public static class TaskTwo extends Thread {
        @Override
        public void run() {
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            SIGN = true;
            System.out.println("修改sign为True");
        }
    }
}
